using System.Text.Json;

namespace BasicData.API.Services
{
    /// <summary>
    /// Redis缓存服务
    /// </summary>
    public class RedisCacheService
    {
        private readonly RedisHelper _redisHelper;
        private readonly ILogger<RedisCacheService> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="redisHelper">Redis帮助类</param>
        /// <param name="logger">日志</param>
        public RedisCacheService(RedisHelper redisHelper, ILogger<RedisCacheService> logger)
        {
            _redisHelper = redisHelper;
            _logger = logger;
        }

        /// <summary>
        /// 获取或添加缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="factory">数据工厂</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>缓存数据</returns>
        public async Task<T> GetOrAddAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
        {
            try
            {
                // 尝试从缓存获取
                if (_redisHelper.Exists(key))
                {
                    _logger.LogInformation("从Redis缓存获取数据: {Key}", key);
                    return _redisHelper.Get<T>(key);
                }

                // 缓存不存在，调用工厂方法获取数据
                _logger.LogInformation("Redis缓存未命中，从数据源获取: {Key}", key);
                var data = await factory();

                // 将数据添加到缓存
                if (data != null)
                {
                    _redisHelper.Set(key, data, expiry);
                    _logger.LogInformation("数据已添加到Redis缓存: {Key}", key);
                }

                return data;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取或添加Redis缓存时出错: {Key}", key);
                // 发生异常时，尝试直接从数据源获取
                return await factory();
            }
        }

        /// <summary>
        /// 移除缓存
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>是否成功</returns>
        public bool Remove(string key)
        {
            try
            {
                _logger.LogInformation("移除Redis缓存: {Key}", key);
                return _redisHelper.Delete(key);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "移除Redis缓存时出错: {Key}", key);
                return false;
            }
        }

        /// <summary>
        /// 按模式移除缓存
        /// </summary>
        /// <param name="pattern">模式</param>
        /// <returns>移除的键数量</returns>
        public int RemoveByPattern(string pattern)
        {
            try
            {
                var keys = _redisHelper.GetAllKeys(pattern).ToList();
                _logger.LogInformation("按模式移除Redis缓存: {Pattern}, 找到 {Count} 个键", pattern, keys.Count);
                
                int count = 0;
                foreach (var key in keys)
                {
                    if (_redisHelper.Delete(key))
                        count++;
                }
                
                return count;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "按模式移除Redis缓存时出错: {Pattern}", pattern);
                return 0;
            }
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="data">数据</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>是否成功</returns>
        public bool Set<T>(string key, T data, TimeSpan? expiry = null)
        {
            try
            {
                _logger.LogInformation("设置Redis缓存: {Key}", key);
                return _redisHelper.Set(key, data, expiry);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置Redis缓存时出错: {Key}", key);
                return false;
            }
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <returns>缓存数据</returns>
        public T Get<T>(string key)
        {
            try
            {
                _logger.LogInformation("获取Redis缓存: {Key}", key);
                return _redisHelper.Get<T>(key);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取Redis缓存时出错: {Key}", key);
                return default;
            }
        }

        /// <summary>
        /// 检查缓存是否存在
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>是否存在</returns>
        public bool Exists(string key)
        {
            try
            {
                return _redisHelper.Exists(key);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查Redis缓存是否存在时出错: {Key}", key);
                return false;
            }
        }

        /// <summary>
        /// 设置缓存过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>是否成功</returns>
        public bool SetExpiry(string key, TimeSpan expiry)
        {
            try
            {
                return _redisHelper.SetExpiry(key, expiry);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置Redis缓存过期时间时出错: {Key}", key);
                return false;
            }
        }
    }
} 